home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / minix / update~4.z / update~4 / lib_stdio_notused_vfscanf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-06  |  6.2 KB  |  269 lines

  1. /*                v f s c a n f
  2.  *
  3.  * Formatted read from a stream. This function uses varargs to
  4.  * obtain the argument list. It is the basis of the family of
  5.  * scanf functions in this stdio implementation.
  6.  *
  7.  * The user is referred to the manual page for a full
  8.  * description of the formats available.
  9.  *
  10.  * The function returns EOF on end of input, and a short count
  11.  * for missing or illegal data items.
  12.  *
  13.  * Patchlevel 1.1
  14.  *
  15.  * Edit History:
  16.  * 05-Sep-1989    Include limits.h if TOLOWER undefined so removing
  17.  *        need to define MINIX when compiling.
  18.  */
  19.  
  20. #include <ctype.h>
  21. #include "stdiolib.h"
  22. #include "bitset.h"
  23.  
  24. #if    defined(BSD)
  25. # include <values.h>
  26. # define TOLOWER(c)    (isupper((c)) ? tolower((c)) : (c))
  27. # define CHARSET    (1 << (BITSPERBYTE))
  28. #endif
  29.  
  30. #if    !defined(TOLOWER)
  31. # include <limits.h>
  32. # define TOLOWER(c)    (tolower((c)))
  33. # define CHARSET    (1 << (CHAR_BIT))
  34.   extern int tolower    P((int));
  35. #endif
  36.  
  37. #define WHITESPACE(c)    ((c)==' '||(c)=='\t'||(c)=='\n')
  38. #define NEXTCH()    (ch = getc(fp))
  39. #define ENDFIELD() \
  40.   if (fieldok) { \
  41.     if (! noassign) items++; \
  42.   } \
  43.   else \
  44.     goto Putback;
  45.  
  46. int vfscanf(fp, fmt, args)
  47.  
  48. FILE *fp;            /* stream */
  49. char *fmt;            /* format */
  50. va_list args;            /* arguments */
  51.  
  52. {
  53.   bitstring(cset, CHARSET);    /* set for %[] */
  54.   int items;            /* number of items done */
  55.   int ch;            /* next character */
  56.   int lch;            /* lowercase version of character */
  57.   int i;            /* general index */
  58.   char *p;            /* string pointer */
  59.   char skipspace;        /* force white space skip */
  60.   char noassign;        /* do not do assignment */
  61.   char longflag;        /* pointer is long */
  62.   char shortflag;        /* pointer is short */
  63.   char fieldok;            /* this field parsed ok */
  64.   char invertedset;        /* inverted set */
  65.   char sign;            /* conversion is signed */
  66.   char negative;        /* number is negative */
  67.   int fieldwidth;        /* width of field */
  68.   unsigned radix;        /* radix for conversion */
  69.   unsigned lastdigit;        /* last digit (0-9) in radix */
  70.   long longv;            /* long value for conversion */
  71.  
  72. /* Prime the look ahead character */
  73.   if (NEXTCH() == EOF)
  74.     return EOF;
  75.  
  76.   for (items = 0; ; fmt++) {
  77.  
  78. /* Skip whitespace in format */
  79.     for (skipspace = 0; WHITESPACE(*fmt); fmt++)
  80.       skipspace = 1;
  81.  
  82. /* Check for end of format or end of input */
  83.     if (*fmt == 0 || ch == EOF)
  84.       goto Putback;
  85.  
  86. /* Check for verbatim character */
  87.     if (*fmt != '%') {
  88.       while (WHITESPACE(ch))
  89.         NEXTCH();
  90.  
  91.       if (ch != *fmt)
  92.         goto Putback;
  93.  
  94.       NEXTCH();
  95.       continue;
  96.     }
  97.  
  98. /* Format precursor seen --- see if assignment required */
  99.     if ((noassign = *++fmt == '*') != 0)
  100.       fmt++;
  101.  
  102. /* Check for width specification */
  103.     fieldwidth = -1;
  104.     if (*fmt >= '0' && *fmt <= '9') {
  105.       for (fieldwidth = 0; *fmt >= '0' && *fmt <= '9'; )
  106.         fieldwidth = fieldwidth * 10 + *fmt++ - '0';
  107.     }
  108.  
  109. /* Check for long or short pointers */
  110.     if ((longflag = *fmt == 'l') != 0 || (shortflag = *fmt == 'h') != 0)
  111.       fmt++;
  112.  
  113. /* Skip whitespace in the input stream */
  114.     if (skipspace || (*fmt != 'c' && *fmt != '[')) {
  115.       while (WHITESPACE(ch))
  116.         NEXTCH();
  117.     }
  118.  
  119. /* Assume that field is not parsed */
  120.     fieldok = 0;
  121.  
  122.     switch (*fmt) {
  123.  
  124.     case 'O': longflag = 1;
  125.     case 'o': radix = 8;  lastdigit = '7'; sign = 0; goto oxud;
  126.     case 'U': longflag = 1;
  127.     case 'u': radix = 10; lastdigit = '9'; sign = 0; goto oxud;
  128.     case 'D': longflag = 1;
  129.     case 'd': radix = 10; lastdigit = '9'; sign = 1; goto oxud;
  130.     case 'X': longflag = 1;
  131.     case 'x': radix = 16; lastdigit = '9'; sign = 0;
  132.  
  133. oxud:
  134.       longv = 0;
  135.       negative = 0;
  136.  
  137. /* Look for sign if number is signed */
  138.       if (fieldwidth != 0 && sign && ch == '+')
  139.     NEXTCH();
  140.       else if (fieldwidth != 0 && sign && ch == '-') {
  141.     negative = 1;
  142.     NEXTCH();
  143.       }
  144.  
  145. /* Scan and convert */
  146.       while (fieldwidth < 0 || fieldwidth--) {
  147.     if (ch >= '0' && ch <= lastdigit)
  148.       ch -= '0';
  149.     else {
  150.       lch = TOLOWER(ch);
  151.       if (lch >= 'a' && (lch += 10 - 'a') < radix)
  152.         ch = lch;
  153.       else
  154.         break;
  155.     }
  156.     longv = longv * radix + ch;
  157.     NEXTCH();
  158.     fieldok = 1;
  159.       }
  160.  
  161. /* Complete the conversion */      
  162.       if (! noassign) {
  163.     if (negative)
  164.       longv = -longv;
  165.     if (longflag)
  166.       if (sign) *va_arg(args, long *)           = longv;
  167.       else      *va_arg(args, unsigned long *)  = longv;
  168.     else if (shortflag)
  169.       if (sign) *va_arg(args, short *)          = (short) longv;
  170.       else      *va_arg(args, unsigned short *) = (unsigned short) longv;
  171.     else
  172.       if (sign) *va_arg(args, int *)            = (int) longv;
  173.       else      *va_arg(args, unsigned int *)   = (unsigned int) longv;
  174.       }
  175.       ENDFIELD();
  176.       break;
  177.  
  178.     case 'c':
  179.       if (fieldwidth == -1)
  180.     fieldwidth = 1;
  181.  
  182. /* Initialise the string pointer */    
  183.       if (! noassign)
  184.         p = va_arg(args, char *);
  185.     
  186.       while (fieldwidth-- && ch >= 0) {
  187.         *p++ = ch;
  188.     NEXTCH();
  189.     fieldok = 1;
  190.       }
  191.       ENDFIELD();
  192.       break;
  193.  
  194.     case 's':
  195.  
  196. /* Initialise the string pointer */    
  197.       if (! noassign)
  198.     p = va_arg(args, char *);
  199.     
  200.       while (fieldwidth < 0 || fieldwidth--) {
  201.         if (ch <= 0 || WHITESPACE(ch))
  202.       break;
  203.     *p++ = ch;
  204.     NEXTCH();
  205.     fieldok = 1;
  206.       }
  207.  
  208. /* Terminate the string with a null */
  209.       if (! noassign)
  210.     *p++ = 0;
  211.       ENDFIELD();
  212.       break;
  213.  
  214.     case '[':
  215.  
  216.  /* Clear the bit set */
  217.       bitempty(cset, CHARSET);
  218.  
  219. /* Check for inverted set */
  220.       if ((invertedset = *++fmt == '^') != 0)
  221.     fmt++;
  222.  
  223. /* Check for right bracket in set */
  224.       if (*fmt == ']')
  225.         bitset(cset, *fmt++);
  226.  
  227. /* Scan    search set, setting bits */
  228.       while (*fmt != 0 && *fmt != ']') {
  229.     if (fmt[1] != '-' || fmt[2] == ']' || fmt[2] == 0 || fmt[0] > fmt[2])
  230.       bitset(cset, *fmt++);
  231.     else {
  232.       for (i = fmt[0]; i <= fmt[2]; i++)
  233.         bitset(cset, i);
  234.       fmt += 3;
  235.     }
  236.       }
  237.  
  238. /* Check for unsatisfactory set construction */
  239.       if (*fmt != ']')
  240.     goto Putback;
  241.  
  242. /* Initialise string pointer */
  243.       if (! noassign)
  244.     p = va_arg(args, char *);
  245.  
  246. /* Scan input for satisfactory characters */
  247.       while (fieldwidth < 0 || fieldwidth--) {
  248.         if (WHITESPACE(ch) || ch <= 0 || ! (bittest(cset, ch) ^ invertedset))
  249.       break;
  250.     *p++ = ch;
  251.     NEXTCH();
  252.     fieldok = 1;
  253.       }
  254.  
  255. /* Terminate string with null */
  256.       if (! noassign)
  257.     *p++ = 0;
  258.       ENDFIELD();
  259.       break;
  260.     }
  261.   }
  262.  
  263. /* Restore the look ahead character */
  264. Putback:
  265.   if (ch != EOF)
  266.     (void) ungetc(ch, fp);
  267.   return items;
  268. }
  269.